package com.tianma315.core.trace.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;

import com.sun.org.apache.bcel.internal.generic.NEW;
import com.tianma315.core.codes.domain.CodesDO;
import com.tianma315.core.codes.service.CodesService;
import com.tianma315.core.common.base.CoreServiceImpl;
import com.tianma315.core.common.domain.ConfigDO;
import com.tianma315.core.common.exception.MessageException;
import com.tianma315.core.common.service.ConfigService;
import com.tianma315.core.constant.StateEnum;
import com.tianma315.core.merchant.service.MerchantService;
import com.tianma315.core.procedures.dao.ProcedureLinkDao;
import com.tianma315.core.procedures.dao.ProceduresDao;
import com.tianma315.core.procedures.domain.ProcedureLinkDO;
import com.tianma315.core.procedures.domain.ProcedureLinkVO;
import com.tianma315.core.procedures.domain.ProceduresDO;
import com.tianma315.core.product.domain.ProductDO;
import com.tianma315.core.product.service.ProductService;
import com.tianma315.core.report.domain.ReportDO;
import com.tianma315.core.report.domain.ReportImgDO;
import com.tianma315.core.report.service.ReportImgService;
import com.tianma315.core.report.service.ReportService;
import com.tianma315.core.report.vo.ReportApiVO;
import com.tianma315.core.scanrecord.domain.ScanRecordDO;
import com.tianma315.core.scanrecord.service.ScanRecordService;
import com.tianma315.core.trace.dao.TraceOutDao;
import com.tianma315.core.trace.domain.TraceOutDO;
import com.tianma315.core.trace.domain.TraceOutFieldDO;
import com.tianma315.core.trace.service.TraceOutFieldService;
import com.tianma315.core.trace.service.TraceOutService;
import com.tianma315.core.trace.service.TraceabilityFileService;
import com.tianma315.core.trace.vo.TraceOutAndFieldVO;
import com.tianma315.core.trace.vo.TraceOutApiVO;
import com.tianma315.core.trace.vo.TraceOutAttrFieldVO;
import com.tianma315.core.trace.vo.TraceOutVO;
import com.tianma315.core.tymenu.dao.TyMenuDataDao;
import com.tianma315.core.tymenu.domain.TyMenuDO;
import com.tianma315.core.tymenu.domain.TyMenuDataVO;
import com.tianma315.core.tymenu.service.TyMenuService;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 
 * <pre>
 * 溯源批次出库记录
 * </pre>
 * <small> 2019-08-08 15:02:49 | Wb</small>
 */
@Service
public class TraceOutServiceImpl extends CoreServiceImpl<TraceOutDao, TraceOutDO> implements TraceOutService {

    @Autowired
    private TraceOutDao traceOutDao;
    @Autowired
    private ProceduresDao proceduresDao;
    @Autowired
    private ProcedureLinkDao procedureLinkDao;
    @Autowired
    private TyMenuDataDao tyMenuDataDao;

//    @Autowired
//    private TraceOutFieldService traceOutFieldService;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private MerchantService merchantService;

    @Autowired
    private ReportService reportService;

    @Autowired
    private ReportImgService reportImgService;

    @Autowired
    private ProductService productService;


    @Autowired
    private CodesService codesService;

    @Autowired
    private ScanRecordService scanRecordService;

    @Autowired
    private TraceOutFieldService traceOutFieldService;

    @Autowired
    private TraceabilityFileService traceabilityFileService;

    @Autowired
    private TyMenuService tyMenuService;

    @Autowired
    private ConfigService configService;

    @Override
    public Page<TraceOutVO> getTraceOutPage(Integer pageNumber, Integer pageSize, TraceOutDO traceOutDTO, Date beginDate, Date endDate) {
        Page page = new Page(pageNumber,pageSize);
        List<TraceOutVO> list = traceOutDao.getTraceOutVO(page,traceOutDTO,beginDate,endDate);
        page.setRecords(list);
        return page;
    }

    @Override
    public TraceOutAndFieldVO getTraceOutById(Integer id) {
        TraceOutAndFieldVO traceOutAndFieldVO = new TraceOutAndFieldVO();
        TraceOutDO traceOutDO = selectById(id);
        BeanUtils.copyProperties(traceOutDO,traceOutAndFieldVO);
        EntityWrapper<TraceOutFieldDO> wrapper = new EntityWrapper<>();
        wrapper.eq("trace_out_id",id);
        List<TraceOutFieldDO> traceOutFieldDOS = traceOutFieldService.selectList(wrapper);
        traceOutAndFieldVO.setTraceOutFieldDOList(traceOutFieldDOS);
        return traceOutAndFieldVO;
    }

    @Transactional
    @Override
    public Boolean addTraceOut(TraceOutAndFieldVO traceOutAndFieldVO) {
        TraceOutDO traceOutDO = new TraceOutDO();
        BeanUtils.copyProperties(traceOutAndFieldVO,traceOutDO);
        traceOutDO.setState(StateEnum.not_del.getCode());
        traceOutDO.setCreateDate(Calendar.getInstance().getTime());
        Boolean result = insert(traceOutDO);

//        TraceabilityFileDO traceabilityFileDO = new TraceabilityFileDO();
//        traceabilityFileDO.setMerchantId(traceOutAndFieldVO.getMerchantId());
//        traceabilityFileDO.setProductId(traceOutAndFieldVO.getProductId().longValue());
//        traceabilityFileDO.setTraceabilityFileName(traceOutAndFieldVO.getBatch());
//        traceabilityFileDO.setCreateBy(Long.parseLong(traceOutAndFieldVO.getCreateBy()));
//        traceabilityFileDO.setTraceOutId(traceOutDO.getTraceOutId());
//        traceabilityFileDO.setCreateDate(Calendar.getInstance().getTime());
//        traceabilityFileDO.setState(StateEnum.not_del.getCode());
//        traceabilityFileService.insert(traceabilityFileDO);

        List<TraceOutFieldDO> list = traceOutAndFieldVO.getTraceOutFieldDOList();
        if (CollectionUtils.isNotEmpty(list)){
            for (TraceOutFieldDO traceOutField:list) {
                traceOutField.setState(StateEnum.not_del.getCode());
                traceOutField.setTraceOutId(traceOutDO.getTraceOutId());
                traceOutFieldService.insert(traceOutField);
            }
        }
        return result;
    }

    @Transactional
    @Override
    public Boolean updateTraceOut(TraceOutAndFieldVO traceOutAndFieldVO) {
        TraceOutDO traceOutDO = new TraceOutDO();
        BeanUtils.copyProperties(traceOutAndFieldVO,traceOutDO);
        Boolean result = updateById(traceOutDO);

        EntityWrapper<TraceOutFieldDO> wrapper = new EntityWrapper<>();
        wrapper.eq("trace_out_id",traceOutDO.getTraceOutId());
        TraceOutFieldDO traceOutFieldDO = new TraceOutFieldDO();
        traceOutFieldDO.setState(StateEnum.is_del.getCode());
        traceOutFieldService.update(traceOutFieldDO,wrapper);

        List<TraceOutFieldDO> list = traceOutAndFieldVO.getTraceOutFieldDOList();
        if (CollectionUtils.isNotEmpty(list)){
            for (TraceOutFieldDO traceOutField:list) {
                traceOutField.setState(StateEnum.not_del.getCode());
                traceOutField.setTraceOutId(traceOutDO.getTraceOutId());
                traceOutFieldService.insert(traceOutField);
            }
        }
        return result;
    }

    @Override
    public Boolean deleteTraceOut(Integer id) {
        TraceOutDO traceOutDO = new TraceOutDO();
        traceOutDO.setState(StateEnum.is_del.getCode());
        traceOutDO.setTraceOutId(id);
        Boolean result = updateById(traceOutDO);
        return result;
    }

    @Override
    public Boolean checkSerial(Integer serial) {
        Boolean result = false;
        EntityWrapper entityWrapper = new EntityWrapper();
//        entityWrapper.eq("merchant_id",merchantId);
        entityWrapper.le("start_serial",serial);
        entityWrapper.ge("end_serial",serial);
        entityWrapper.eq("state",0);
        Integer count = selectCount(entityWrapper);
        if(count.equals(0)){
            result = true;
        }
        return result;
    }

    @Override
    public JSONObject getTraceOutInfo(String code) {
        JSONObject result = null;
        TraceOutApiVO traceOutApiVO = new TraceOutApiVO();

            //根据code查出序号
            CodesDO codes =codesService.getCodesBySmallCode(code);
            if (codes==null){
               throw new MessageException("该码不存在！");
            }
            Integer serial = Integer.parseInt(codes.getSequence());
            //根据序号查出出库记录
            TraceOutDO traceOutDO = getTraceOutDOBySerial(serial);

            if (traceOutDO != null){
                Integer tfId = traceOutDO.getTraceabilityFileId();
                result = traceabilityFileService.getDataByTraceabilityFileId(tfId);
                //添加扫码记录
                putScanRecord(code, result, tfId);
                if (traceOutDO.getReportId()!=null){
                    ReportApiVO reportApiVO = new ReportApiVO();
                    Integer reportId = traceOutDO.getReportId();
                    ReportDO reportDO = reportService.selectById(reportId);
                    List<ReportImgDO> reportImgDOS = reportImgService.getReportImgByReportId(reportId);
                    reportApiVO.setReportImgDOList(reportImgDOS);
                    reportApiVO.setReportDO(reportDO);
                    result.put("reportApiVO",reportApiVO);
                }

                //
                String accessToken = configService.getValuByKey("accessToken");
                if (!accessToken.isEmpty()){
                    result.put("accessToken",accessToken);
                }else {
                    result.put("accessToken","");
                }

            }else{
                throw new MessageException("该码尚未出库！");
            }

        return result;
    }

    private void putScanRecord(String code, JSONObject result, Integer tfId) {
        Wrapper<ScanRecordDO> wrapper = new EntityWrapper<>();
        wrapper.eq("code",code);
        wrapper.eq("trace_file_id",tfId);
        ScanRecordDO scanRecordDO = scanRecordService.selectOne(wrapper);
        if (scanRecordDO!=null){
            scanRecordDO.setScanNumber(scanRecordDO.getScanNumber()+1);
            scanRecordService.updateById(scanRecordDO);
            result.put("scanRecord",scanRecordDO);
        }else {
            ScanRecordDO scanRecord = new ScanRecordDO();
            scanRecord.setCode(code);
            scanRecord.setScanNumber(1);
            scanRecord.setCreatedDate(new Date());
            scanRecord.setTraceFileId(tfId.longValue());
            scanRecordService.insert(scanRecord);
            result.put("scanRecord",scanRecord);
        }
    }

    @Override
    public List<ProcedureLinkVO> selectContent(Integer productId, Integer traceabilityFileId) {
        //通过产品Id获取绑定的流程模板Id
        Integer procedureId = getProceureIdByProductId(productId);
        //获取模板的所有环节流程
        Wrapper<ProcedureLinkDO> wrapper2 = new EntityWrapper<>();
        wrapper2.eq("state",0).eq("procedures_id",procedureId).orderBy("sort");
        List<ProcedureLinkDO> procedureLinkDOS = procedureLinkDao.selectList(wrapper2);
        if (procedureLinkDOS.isEmpty()){
           return null;
        }

        //判断是否已录入添加（判断规则：根据档案Id和环节Id是否存在）
        updateIsAdd(traceabilityFileId, procedureLinkDOS);

        //分级环节的封装
        List<ProcedureLinkVO> parentProVo = getParentVo(procedureLinkDOS);
        return parentProVo;
    }

    private  List<ProcedureLinkVO> getParentVo(List<ProcedureLinkDO> procedureLinkDOS) {
        //一级环节
        List<ProcedureLinkVO> parentProVo = new ArrayList<>();
        //剩余二级环节
        List<ProcedureLinkDO> procedureLinkDS = procedureLinkDOS.stream().filter(dos -> {
            if (dos.getType() == 0) {
                ProcedureLinkVO procedureLinkVO = new ProcedureLinkVO();
                BeanUtils.copyProperties(dos, procedureLinkVO);
                parentProVo.add(procedureLinkVO);
            }
            return dos.getType() == 1;
        }).collect(Collectors.toList());
       /* Iterator<ProcedureLinkDO> itr = procedureLinkDOS.iterator();
        while(itr.hasNext()) {
            ProcedureLinkDO next = itr.next();
            if (next.getType()==0) {
                ProcedureLinkVO procedureLinkVO = new ProcedureLinkVO();
                BeanUtils.copyProperties(next,procedureLinkVO);
                parentProVo.add(procedureLinkVO);
                itr.remove();
            }
        }*/
       //一级环节遍历
        parentProVo.stream().forEach(parent->{
            //是否符合条件 有子环节
            if (parent.getIsParent()==1) {
                if (!procedureLinkDS.isEmpty()){
                    //遍历子环节 封装到父环节中去
                    List<ProcedureLinkDO> proSonDos = new ArrayList<>();
                    procedureLinkDS.stream().forEach(ds->{
                        if (ds.getParentId()==parent.getProcedureLinkId()) {
                            proSonDos.add(ds);
                            parent.setProSonDos(proSonDos);
                        }
                    });
                }
            }
        });
       /* Iterator<ProcedureLinkVO> iterator = parentProVo.iterator();
        while (iterator.hasNext()){
            ProcedureLinkVO next = iterator.next();
            if (next.getIsParent()==1) {
                for (ProcedureLinkDO procedureLinkDO : procedureLinkDOS) {
                    if (procedureLinkDO.getParentId()==next.getProcedureLinkId()) {
                        List<ProcedureLinkDO> proSonDos = new ArrayList<>();
                        proSonDos.add(procedureLinkDO);
                        next.setProSonDos(proSonDos);
                    }
                }
            }
        }*/
        return parentProVo;
    }

    private Integer getProceureIdByProductId(Integer productId) {
        ProductDO productDO = productService.selectById(productId);
        Integer procedureId = productDO.getProcedureId();
        if (procedureId==null){
            throw new MessageException("产品未绑定的模板");
        }
        return procedureId;
    }

    private void updateIsAdd(Integer traceabilityFileId, List<ProcedureLinkDO> procedureLinkDOS) {
        for (int i = 0; i < procedureLinkDOS.size(); i++) {
            EntityWrapper<TyMenuDO> tyMenuDOwrapper = new EntityWrapper<>();
            tyMenuDOwrapper.eq("procedure_link_id",procedureLinkDOS.get(i).getProcedureLinkId());
            tyMenuDOwrapper.eq("traceability_file_id",traceabilityFileId);
            tyMenuDOwrapper.eq("is_delete",0);
            List<TyMenuDO> tyMenuDOS = tyMenuService.selectList(tyMenuDOwrapper);
            if (tyMenuDOS.isEmpty()){
                procedureLinkDOS.get(i).setIsAdd(0);
            }else {
                procedureLinkDOS.get(i).setIsAdd(1);
            }
        }
    }

    @Override
    public List<TyMenuDataVO> getTyMenuDataDOS(Integer id, Integer traceabilityFileId) {
        Wrapper<TyMenuDO> tyMenuDOWrapper = new EntityWrapper<>();
        tyMenuDOWrapper.eq("procedure_link_id",id);
        tyMenuDOWrapper.eq("traceability_file_id",traceabilityFileId);
        tyMenuDOWrapper.eq("is_delete",0);
        List<TyMenuDO> tyMenuDOS = tyMenuService.selectList(tyMenuDOWrapper);
        List<TyMenuDataVO> tyMenuDataDOS = tyMenuDataDao.selectVOList(tyMenuDOS.get(0).getMenuId());
        for (int i = 0; i < tyMenuDataDOS.size(); i++) {
            TyMenuDataVO tyMenuData = tyMenuDataDOS.get(i);
            if (tyMenuData.getType() == 1);{
                List<String> pics = new ArrayList<>();
                String dataValue = tyMenuDataDOS.get(i).getDataValue();
                String[] split = dataValue.split(",");
                if (split.length>1){
                    for (int j = 0; j < split.length; j++) {
                        pics.add(split[j]);
                    }
                }else if (split.length == 1){
                    pics.add(split[0]);
                }
                tyMenuData.setPics(pics);
            }
        }
        return tyMenuDataDOS;
    }

    @Override
    public Page<TraceOutVO> getTraceOutPage(Integer pageNumber, int pageSize, Integer productId) {
        Page page = new Page(pageNumber,pageSize);
        List<TraceOutVO> list;
        list = traceOutDao.getListByProductId(page,productId);
        page.setRecords(list);
      /*  //因为连表查询total会出现错误，手动设置
        Wrapper<TraceOutDO> wrapper = new EntityWrapper<>();
        wrapper.eq("product_id",productId).eq("state",0);
        int total = selectCount(wrapper);
        page.setTotal(total);*/
        return page;
    }


    public TraceOutDO getTraceOutDOBySerial( Integer serial){
        EntityWrapper<TraceOutDO> traceOutDOEntityWrapper = new EntityWrapper<>();
        traceOutDOEntityWrapper.le("start_serial",serial);
        traceOutDOEntityWrapper.ge("end_serial",serial);
        traceOutDOEntityWrapper.eq("state",0);
        TraceOutDO traceOutDO = selectOne(traceOutDOEntityWrapper);
        return traceOutDO;
    }

}
